package com.hankol.winecellar.utils

import android.view.View
import androidx.recyclerview.widget.OrientationHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SnapHelper

/**
 * <pre>
 *  @author: Meng
 * --->time： 2020/11/27
 * ---> dec：
 *@param itemCount 每次滑动Item个数
 * <pre>
 */
class PagerSnapHelper(private val itemCount: Int) : SnapHelper() {
    private val TAG = "PagerSnapHelper"

    //垂直滑动
    private var mVerticalHelper: OrientationHelper? = null

    //水平滑动
    private var mHorizontalHelper: OrientationHelper? = null

    //款
    private var mRecyclerViewWidth = 0

    //高
    private var mRecyclerViewHeight = 0

    //需要滑动距离
    private var mCurrentScrolledX = 0
    private var mCurrentScrolledY = 0

    //滑动距离
    private var mScrolledX = 0
    private var mScrolledY = 0

    //防止惯性滑动
    private var mFlung = false

    /**
     * RecyclerView 滑动监听器 获取滑动总距离
     */
    private val mScrollListener = object : RecyclerView.OnScrollListener() {
        private var scrolledByUser = false

        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            if (newState == RecyclerView.SCROLL_STATE_DRAGGING) scrolledByUser = true
            if (newState == RecyclerView.SCROLL_STATE_IDLE && scrolledByUser) {
                scrolledByUser = false
            }
        }

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            mScrolledX += dx
            mScrolledY += dy
            if (scrolledByUser) {
                mCurrentScrolledX += dx
                mCurrentScrolledY += dy
            }
        }
    }

    override fun attachToRecyclerView(recyclerView: RecyclerView?) {
        super.attachToRecyclerView(recyclerView)
        recyclerView?.run {
            addOnScrollListener(mScrollListener)
            post {
                println("$TAG RecyclerViewWidth: $width===$height")

                mRecyclerViewWidth = width
                mRecyclerViewHeight = height
            }
        }
    }

    /**
     * Override this method to snap to a particular point within the target view or the container
     * view on any axis.
     * <p>
     * This method is called when the {@link SnapHelper} has intercepted a fling and it needs
     * to know the exact distance required to scroll by in order to snap to the target view.
     *
     * @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
     *                      {@link RecyclerView}
     * @param targetView the target view that is chosen as the view to snap
     *
     * @return the output coordinates the put the result into. out[0] is the distance
     * on horizontal axis and out[1] is the distance on vertical axis.
     *
     * 找到需要对齐的 ItemView
     * @TODO out[0] 是水平轴的距离 （x）   out[1] 垂直轴的距离(y)
     *
     */
    override fun calculateDistanceToFinalSnap(
        layoutManager: RecyclerView.LayoutManager,
        targetView: View
    ): IntArray? {
        val out = IntArray(2)
        if (layoutManager.canScrollHorizontally()) {
            out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager))
            out[1] = 0
        } else if (layoutManager.canScrollVertically()) {
            out[0] = 0
            out[1] = distanceToStart(targetView, getVerticalHelper(layoutManager))
        }
        return out
    }

    private fun distanceToStart(targetView: View, orientationHelper: OrientationHelper): Int {
        return orientationHelper.getDecoratedStart(targetView) - orientationHelper.startAfterPadding
    }

    /**
     * Override to provide a particular adapter target position for snapping.
     *
     * @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
     *                      {@link RecyclerView}
     * @param velocityX fling velocity on the horizontal axis
     * @param velocityY fling velocity on the vertical axis
     *
     * @return the target adapter position to you want to snap or {@link RecyclerView#NO_POSITION}
     *         if no snapping should happen
     *
     *计算 snapView 到要对齐的位置之间的距离。
     */
    override fun findTargetSnapPosition(
        layoutManager: RecyclerView.LayoutManager?,
        velocityX: Int,
        velocityY: Int
    ): Int {
        //获取当前滑动到的位置 @TODO targetPosition如果为-1代表滑动到头了  不能在进行滑动
        val targetPosition = getTargetPosition()
        mFlung = targetPosition != RecyclerView.NO_POSITION
        println("$TAG findTargetSnapPosition, pos: $targetPosition")
        return targetPosition
    }

    /**
     *
     * Override this method to provide a particular target view for snapping.
     * <p>
     * This method is called when the {@link SnapHelper} is ready to start snapping and requires
     * a target view to snap to. It will be explicitly called when the scroll state becomes idle
     * after a scroll. It will also be called when the {@link SnapHelper} is preparing to snap
     * after a fling and requires a reference view from the current set of child views.
     * <p>
     * If this method returns {@code null}, SnapHelper will not snap to any view.
     *
     * @param layoutManager the {@link RecyclerView.LayoutManager} associated with the attached
     *                      {@link RecyclerView}
     *
     * @return the target view to which to snap on fling or end of scroll
     *
     * 是用来帮助对齐 ItemView 的
     */
    override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
        if (mFlung) {
            resetCurrentScrolled()
            mFlung = false
            return null
        }
        if (layoutManager == null) return null
        val targetPosition = getTargetPosition()
        println("$TAG findSnapView, pos: $targetPosition")
        if (targetPosition == RecyclerView.NO_POSITION) return null
        layoutManager.startSmoothScroll(createScroller(layoutManager).apply {
            this?.targetPosition = targetPosition
        })
        return null
    }

    private fun getTargetPosition(): Int {
        println("$TAG getTargetPosition, mScrolledX: $mScrolledX, mCurrentScrolledX: $mCurrentScrolledX")
        /**
         * @param page 获取需要滑动Item个数
         */
        val page = when {
            mCurrentScrolledX > 0 -> mScrolledX / mRecyclerViewWidth + 1
            mCurrentScrolledX < 0 -> mScrolledX / mRecyclerViewWidth
            mCurrentScrolledY > 0 -> mScrolledY / mRecyclerViewHeight + 1
            mCurrentScrolledY < 0 -> mScrolledY / mRecyclerViewHeight
            else -> RecyclerView.NO_POSITION
        }
        resetCurrentScrolled()
        return if (page == RecyclerView.NO_POSITION) RecyclerView.NO_POSITION else page * itemCount
    }

    //重新赋值xy
    private fun resetCurrentScrolled() {
        mCurrentScrolledX = 0
        mCurrentScrolledY = 0
    }

    private fun getVerticalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
        if (mVerticalHelper == null || mVerticalHelper!!.layoutManager !== layoutManager) {
            mVerticalHelper = OrientationHelper.createVerticalHelper(layoutManager)
        }
        return mVerticalHelper!!
    }

    private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
        if (mHorizontalHelper == null || mHorizontalHelper!!.layoutManager !== layoutManager) {
            mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager)
        }
        return mHorizontalHelper!!
    }
}